#pragma once

#include <iostream>
#include <fstream>
#include <String>
#include "CSVGenerator.h"
#include "grammarNormalizer.h"
#include "surveyAlligatorException.h"
#include "InputValidator.h"
#include "SurveyAlligatorConfig.h"


namespace SurveyAlligator {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::IO;
	using namespace System::Reflection;

	/// <summary>
	/// Summary for SurveyAlligatorForm
	///
	/// WARNING: If you change the name of this class, you will need to change the
	///          'Resource File Name' property for the managed resource compiler tool
	///          associated with all .resx files this class depends on.  Otherwise,
	///          the designers will not be able to interact properly with localized
	///          resources associated with this form.
	/// </summary>
	public ref class SurveyAlligatorForm: public System::Windows::Forms::Form
	{
	public:
		SurveyAlligatorForm(void)
		{
			InitializeComponent();
			
			// Access the Manifest Resource Stream to obtain the Spartans logo
			Assembly^ _assembly;
			Stream ^_imageStream;
			
			try
			{
				_assembly = Assembly::GetExecutingAssembly();
				_imageStream = _assembly->GetManifestResourceStream("spartans.bmp");
			}
			catch(Exception^ ex)
			{
				MessageBox::Show("Error accessing resources!",ex->Message);
			}

			try
			{
				this->pictureBox1->BackgroundImage = gcnew Bitmap(_imageStream);
				this->pictureBox1->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Center;
			}
			catch(Exception^ ex)
			{
				MessageBox::Show("Error creating image!",ex->Message); 
			}
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~SurveyAlligatorForm()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Panel^  Panel_action;
	private: System::Windows::Forms::Button^  Button_submit;



	private: System::Windows::Forms::WebBrowser^  webBrowser1;


	private: System::Windows::Forms::ProgressBar^  progressBar;
	private: System::Windows::Forms::TextBox^  msglabel;
	private: System::Windows::Forms::MenuStrip^  menuStrip1;
	private: System::Windows::Forms::ToolStripMenuItem^  fileToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  loadFormToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  submitToolStripMenuItem;
	private: System::Windows::Forms::ToolStripSeparator^  toolStripSeparator1;
	private: System::Windows::Forms::ToolStripMenuItem^  exitToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  helpToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  aboutSurveyAlligatorToolStripMenuItem;
	private: System::Windows::Forms::Button^  button_ResetForm;
	private: System::String^ surveyFilename;
	private: System::String^ surveyFormForReset;
	private: SurveyAlligatorConfig^ globalConfig;
	private: System::Windows::Forms::PictureBox^  pictureBox1;
	private: System::Windows::Forms::Label^  label1;
	private: System::Windows::Forms::ToolStripMenuItem^  activateDebugModeToolStripMenuItem;
	private: System::Windows::Forms::ToolStripMenuItem^  deactivateDebugModeToolStripMenuItem;


	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->Panel_action = (gcnew System::Windows::Forms::Panel());
			this->button_ResetForm = (gcnew System::Windows::Forms::Button());
			this->msglabel = (gcnew System::Windows::Forms::TextBox());
			this->Button_submit = (gcnew System::Windows::Forms::Button());
			this->progressBar = (gcnew System::Windows::Forms::ProgressBar());
			this->webBrowser1 = (gcnew System::Windows::Forms::WebBrowser());
			this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());
			this->fileToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->loadFormToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->submitToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->toolStripSeparator1 = (gcnew System::Windows::Forms::ToolStripSeparator());
			this->exitToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->helpToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->activateDebugModeToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->deactivateDebugModeToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->aboutSurveyAlligatorToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
			this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->Panel_action->SuspendLayout();
			this->menuStrip1->SuspendLayout();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox1))->BeginInit();
			this->SuspendLayout();
			// 
			// Panel_action
			// 
			this->Panel_action->Controls->Add(this->button_ResetForm);
			this->Panel_action->Controls->Add(this->msglabel);
			this->Panel_action->Controls->Add(this->Button_submit);
			this->Panel_action->Controls->Add(this->progressBar);
			this->Panel_action->Location = System::Drawing::Point(0, 522);
			this->Panel_action->Name = L"Panel_action";
			this->Panel_action->Size = System::Drawing::Size(793, 47);
			this->Panel_action->TabIndex = 0;
			// 
			// button_ResetForm
			// 
			this->button_ResetForm->Enabled = false;
			this->button_ResetForm->Font = (gcnew System::Drawing::Font(L"Tahoma", 9.75F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(0)));
			this->button_ResetForm->Location = System::Drawing::Point(12, 4);
			this->button_ResetForm->Name = L"button_ResetForm";
			this->button_ResetForm->Size = System::Drawing::Size(85, 36);
			this->button_ResetForm->TabIndex = 3;
			this->button_ResetForm->Text = L"&Reset";
			this->button_ResetForm->UseVisualStyleBackColor = true;
			this->button_ResetForm->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::button_ResetForm_Click);
			// 
			// msglabel
			// 
			this->msglabel->AllowDrop = true;
			this->msglabel->Location = System::Drawing::Point(128, 4);
			this->msglabel->Multiline = true;
			this->msglabel->Name = L"msglabel";
			this->msglabel->Size = System::Drawing::Size(538, 36);
			this->msglabel->TabIndex = 2;
			this->msglabel->Visible = false;
			// 
			// Button_submit
			// 
			this->Button_submit->Enabled = false;
			this->Button_submit->Font = (gcnew System::Drawing::Font(L"Tahoma", 9.75F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(0)));
			this->Button_submit->Location = System::Drawing::Point(694, 4);
			this->Button_submit->Name = L"Button_submit";
			this->Button_submit->Size = System::Drawing::Size(85, 36);
			this->Button_submit->TabIndex = 0;
			this->Button_submit->Text = L"&Submit";
			this->Button_submit->UseVisualStyleBackColor = true;
			this->Button_submit->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::button1_Click);
			// 
			// progressBar
			// 
			this->progressBar->Location = System::Drawing::Point(339, 20);
			this->progressBar->Name = L"progressBar";
			this->progressBar->Size = System::Drawing::Size(125, 20);
			this->progressBar->TabIndex = 2;
			this->progressBar->Visible = false;
			// 
			// webBrowser1
			// 
			this->webBrowser1->Location = System::Drawing::Point(12, 37);
			this->webBrowser1->MinimumSize = System::Drawing::Size(20, 20);
			this->webBrowser1->Name = L"webBrowser1";
			this->webBrowser1->Size = System::Drawing::Size(770, 478);
			this->webBrowser1->TabIndex = 1;
			this->webBrowser1->Url = (gcnew System::Uri(L"", System::UriKind::Relative));
			// 
			// menuStrip1
			// 
			this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(2) {this->fileToolStripMenuItem, 
				this->helpToolStripMenuItem});
			this->menuStrip1->Location = System::Drawing::Point(0, 0);
			this->menuStrip1->Name = L"menuStrip1";
			this->menuStrip1->Size = System::Drawing::Size(792, 24);
			this->menuStrip1->TabIndex = 3;
			this->menuStrip1->Text = L"menuStrip1";
			// 
			// fileToolStripMenuItem
			// 
			this->fileToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(4) {this->loadFormToolStripMenuItem, 
				this->submitToolStripMenuItem, this->toolStripSeparator1, this->exitToolStripMenuItem});
			this->fileToolStripMenuItem->Name = L"fileToolStripMenuItem";
			this->fileToolStripMenuItem->Size = System::Drawing::Size(35, 20);
			this->fileToolStripMenuItem->Text = L"&File";
			// 
			// loadFormToolStripMenuItem
			// 
			this->loadFormToolStripMenuItem->Name = L"loadFormToolStripMenuItem";
			this->loadFormToolStripMenuItem->Size = System::Drawing::Size(135, 22);
			this->loadFormToolStripMenuItem->Text = L"&Load Form";
			this->loadFormToolStripMenuItem->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::loadFormToolStripMenuItem_Click);
			// 
			// submitToolStripMenuItem
			// 
			this->submitToolStripMenuItem->Enabled = false;
			this->submitToolStripMenuItem->Name = L"submitToolStripMenuItem";
			this->submitToolStripMenuItem->Size = System::Drawing::Size(135, 22);
			this->submitToolStripMenuItem->Text = L"&Submit";
			this->submitToolStripMenuItem->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::submitToolStripMenuItem_Click);
			// 
			// toolStripSeparator1
			// 
			this->toolStripSeparator1->Name = L"toolStripSeparator1";
			this->toolStripSeparator1->Size = System::Drawing::Size(132, 6);
			// 
			// exitToolStripMenuItem
			// 
			this->exitToolStripMenuItem->Name = L"exitToolStripMenuItem";
			this->exitToolStripMenuItem->Size = System::Drawing::Size(135, 22);
			this->exitToolStripMenuItem->Text = L"E&xit";
			this->exitToolStripMenuItem->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::exitToolStripMenuItem_Click);
			// 
			// helpToolStripMenuItem
			// 
			this->helpToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(3) {this->activateDebugModeToolStripMenuItem, 
				this->deactivateDebugModeToolStripMenuItem, this->aboutSurveyAlligatorToolStripMenuItem});
			this->helpToolStripMenuItem->Name = L"helpToolStripMenuItem";
			this->helpToolStripMenuItem->Size = System::Drawing::Size(40, 20);
			this->helpToolStripMenuItem->Text = L"Help";
			// 
			// activateDebugModeToolStripMenuItem
			// 
			this->activateDebugModeToolStripMenuItem->Name = L"activateDebugModeToolStripMenuItem";
			this->activateDebugModeToolStripMenuItem->Size = System::Drawing::Size(200, 22);
			this->activateDebugModeToolStripMenuItem->Text = L"Activate Debug Mode";
			this->activateDebugModeToolStripMenuItem->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::activateDebugModeToolStripMenuItem_Click);
			// 
			// deactivateDebugModeToolStripMenuItem
			// 
			this->deactivateDebugModeToolStripMenuItem->Name = L"deactivateDebugModeToolStripMenuItem";
			this->deactivateDebugModeToolStripMenuItem->Size = System::Drawing::Size(200, 22);
			this->deactivateDebugModeToolStripMenuItem->Text = L"Deactivate Debug Mode";
			this->deactivateDebugModeToolStripMenuItem->Visible = false;
			this->deactivateDebugModeToolStripMenuItem->Click += gcnew System::EventHandler(this, &SurveyAlligatorForm::deactivateDebugModeToolStripMenuItem_Click);
			// 
			// aboutSurveyAlligatorToolStripMenuItem
			// 
			this->aboutSurveyAlligatorToolStripMenuItem->Name = L"aboutSurveyAlligatorToolStripMenuItem";
			this->aboutSurveyAlligatorToolStripMenuItem->Size = System::Drawing::Size(200, 22);
			this->aboutSurveyAlligatorToolStripMenuItem->Text = L"&About SurveyAlligator";
			// 
			// pictureBox1
			// 
			this->pictureBox1->BackColor = System::Drawing::SystemColors::Window;
			this->pictureBox1->Location = System::Drawing::Point(11, 37);
			this->pictureBox1->Name = L"pictureBox1";
			this->pictureBox1->Size = System::Drawing::Size(770, 478);
			this->pictureBox1->TabIndex = 4;
			this->pictureBox1->TabStop = false;
			// 
			// label1
			// 
			this->label1->AutoSize = true;
			this->label1->BackColor = System::Drawing::SystemColors::Window;
			this->label1->Font = (gcnew System::Drawing::Font(L"Times New Roman", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(0)));
			this->label1->Location = System::Drawing::Point(262, 457);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(269, 22);
			this->label1->TabIndex = 5;
			this->label1->Text = L"Please load a valid survey form.";
			// 
			// SurveyAlligatorForm
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->AutoSize = true;
			this->AutoSizeMode = System::Windows::Forms::AutoSizeMode::GrowAndShrink;
			this->ClientSize = System::Drawing::Size(792, 566);
			this->Controls->Add(this->label1);
			this->Controls->Add(this->pictureBox1);
			this->Controls->Add(this->webBrowser1);
			this->Controls->Add(this->Panel_action);
			this->Controls->Add(this->menuStrip1);
			this->MainMenuStrip = this->menuStrip1;
			this->Name = L"SurveyAlligatorForm";
			this->Text = L"SurveyAlligator";
			this->Panel_action->ResumeLayout(false);
			this->Panel_action->PerformLayout();
			this->menuStrip1->ResumeLayout(false);
			this->menuStrip1->PerformLayout();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox1))->EndInit();
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e){
				 
		System::Windows::Forms::HtmlDocument^ currentDoc = this->webBrowser1->Document;

		//// Perform final validation here...
		System::String^ errorMessage;

		errorMessage = "";
		errorMessage = InputValidator::validateFormInput(this->webBrowser1);
			
		if (errorMessage != "") {
			MessageBox::Show(errorMessage,"Input Error");
		}
		else {

			// Alrite ... Time to write to file.
			CSVGenerator^ csvgen;
			try {
			csvgen = gcnew CSVGenerator(this->globalConfig->getCsvFileLocation(), this->globalConfig);

			System::Windows::Forms::HtmlElementCollection^ formElements = currentDoc->GetElementsByTagName("form"); // get all the form html tags in the document
			System::Collections::IEnumerator^ ienumF = formElements->GetEnumerator();
			System::Windows::Forms::HtmlElement^ formelement = nullptr;
			if(ienumF->MoveNext())
			{
				// extract only the first form element			
				formelement = (HtmlElement^)ienumF->Current;
			}
			
			if(formelement == nullptr)
			throw gcnew surveyAlligatorException("<form></form> tag missing. All input elements for a survey data must be enclosed\n in a <form> html tag."); 
			
			csvgen->startDebug();
			this->displayDebugMsg("Starting CSV Generation ...", true);

			if(this->globalConfig->getUniquenessActive()->ToLower()->Equals("yes"))
			{
				// Uniqueness active value is 'yes'. So we may need to replace data in csv file OR append to it
				if(this->globalConfig->getReplacementPolicy()->ToLower()->Equals("replacement"))
				{
				 // Policy is replacement. Replace in data in csv file
				 				 
				 System::Windows::Forms::HtmlElement^ primElem = nullptr;
				 primElem = currentDoc->GetElementById(this->globalConfig->getUniquenessKeyId());
		  		 
				 csvgen->replaceInFile(formelement, primElem);

				}
				else if(this->globalConfig->getReplacementPolicy()->ToLower()->Equals("append"))
				{
				  // Policy is append. Simply append data
					csvgen->appendToFile(formelement);
					
				}
				else throw gcnew surveyAlligatorException("Invalid value for replacement policy in uniqueness tag.");

			}
			else 
			{
			  // uniqueness active value is no. Simply append data
			  csvgen->appendToFile(formelement);
			  
			}
			
			this->displayDebugMsg(Environment::NewLine+csvgen->getDebugMsg()+Environment::NewLine+" CSV Generation completed."+Environment::NewLine, true);
			csvgen->clearDebugMsg();
			MessageBox::Show("          Your answers were sucessfully saved.\n\n                 Thanks for participating.\n\n  The survey will be cleared for the next subject.","SurveyAlligator - Survey Completed");
			this->webBrowser1->Document->OpenNew(true);
			this->webBrowser1->Document->Write(this->surveyFormForReset);

			} // end of try
			catch(surveyAlligatorException ^e)
			{
				if(csvgen != nullptr)
				{
					// If csvgen object exists. It may not exist if the CSVGenerator constructor threw an exception.
					this->displayDebugMsg(csvgen->getDebugMsg(), true);
					csvgen->clearDebugMsg();
				}
				MessageBox::Show(e->getMessage(),"CSV Generator reports this error: ",MessageBoxButtons::OK,MessageBoxIcon::Error);
				this->displayDebugMsg("Exception occured:"+Environment::NewLine+"CSV Generator reports this error:"+Environment::NewLine+e->getMessage(), true);
			}
			catch(System::Exception^ e)
			{
				MessageBox::Show(e->Message,"CSV Generator reports this error: ",MessageBoxButtons::OK,MessageBoxIcon::Error);
				this->displayDebugMsg("Exception occured in CSV Generator: "+Environment::NewLine+e->Message, true);
			
			}



		} // end of else

	 } // end of method


private: System::String^ getFileContent(System::IO::FileInfo^ fi1){
   String^ temp = "";
   String^ content = "";
   System::IO::StreamReader^ sr = fi1->OpenText();
   try{
      while ( temp = sr->ReadLine() ){
         content = content + temp;
      }
   } catch (Exception ^ e){
	   displayDebugMsg(e->Message,true);
      surveyAlligatorException^ ex = gcnew surveyAlligatorException("There was a problem reading the selected file.");
	  throw (ex);
   
   }finally{ // Close the StreamReader
	   if ( sr ){
		   delete (IDisposable^)sr;
	   }
   }
   
   return content;
}

private: System::Void loadFormToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
	// Event for Load html file button
    System::Windows::Forms::OpenFileDialog loadFileDialog;
    System::Windows::Forms::DialogResult dr =  loadFileDialog.ShowDialog();
    if(dr == System::Windows::Forms::DialogResult::OK)				 {
		 System::IO::FileInfo^ file = (gcnew System::IO::FileInfo(loadFileDialog.FileName));
		 if(file->Exists){
			try {
				String^ content = getFileContent(file);
    			 if (grammarNormalizer::checkValidGrammar(content)){
					content = grammarNormalizer::embedJavaScriptValidationIntoHTML(content);
					this->surveyFilename = file->FullName;
					this->webBrowser1->Document->OpenNew(true);
					this->webBrowser1->Document->Write(content);
					// Preserve the validated and embedded survey form content 
					// to support the reset function
					this->surveyFormForReset = content;

					this->Button_submit->Enabled = true;
					this->button_ResetForm->Enabled = true;
					this->submitToolStripMenuItem->Enabled = true;

					// Initialize the global configurations
					// First time initialization of global config here	
					globalConfig->instance(content);
					this->Text = "SurveyAlligator   :::   " + globalConfig->getHtmlInputFileTitle();
	
					 }else {
						surveyAlligatorException^ ex = gcnew surveyAlligatorException("The file does not satisfy the grammar.");
						throw (ex);	
					 }
					}catch (surveyAlligatorException ^e){
  		    			MessageBox::Show(e->getMessage(),"The file "+file->Name+" does not satisfy the grammar.",MessageBoxButtons::OK,MessageBoxIcon::Error);
						displayDebugMsg (e->getMessage(),true);
					}
				
				// Hide the splash picture box and label
				hideSplashComponents();
				
				}
			}		 
		}

private: void hideSplashComponents() {
	pictureBox1->Hide();
	label1->Hide();
}

private: void displayDebugMsg(System::String^ s, bool append){
	if(append)
		this->msglabel->Text += "\n"+s;
	else this->msglabel->Text = s;
	this->Update();
}


private: System::Void exitToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
			 Application::Exit();
		 }

private: System::Void submitToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
			 this->button1_Click(sender,e);
		 }

private: System::Void button_ResetForm_Click(System::Object^  sender, System::EventArgs^  e) {
			 this->webBrowser1->Document->OpenNew(true);
			 this->webBrowser1->Document->Write(this->surveyFormForReset);
		 }

private: System::Void activateDebugModeToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
	msglabel->Visible = true;
	deactivateDebugModeToolStripMenuItem->Visible = true;
	activateDebugModeToolStripMenuItem->Visible = false;
}
private: System::Void deactivateDebugModeToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {
	msglabel->Visible = false;
	deactivateDebugModeToolStripMenuItem->Visible = false;
	activateDebugModeToolStripMenuItem->Visible = true;
}
}; // end of class definition
} // end of namespace

